﻿using AJWPFAdmin.Core.Enums;
using AJWPFAdmin.Core.GlobalEvents;
using AJWPFAdmin.Core.HardwareSDKS.FFmpeg;
using AJWPFAdmin.Core.HardwareSDKS.HIKVision;
using AJWPFAdmin.Core.Models;
using AJWPFAdmin.Core.Utils;
using Masuit.Tools.Systems;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using Yitter.IdGenerator;
using static AJWPFAdmin.Core.HardwareSDKS.HIKVision.CHCNetSDK;

namespace AJWPFAdmin.Core.HardwareSDKS.Models
{
    public class HIKVisionDevice : DeviceInfo
    {

        public enum BarrierCtrlType : byte
        {
            关闭,
            开启,
            停止,
            锁定,
            解锁
        }

        protected static object _lock = new object();

        private int _alarmHandleId;

        private int _realPlayHandle = -1;

        private CHCNetSDK.NET_DVR_DEVICEINFO_V40 _deviceInfo;

        private CHCNetSDK.NET_DVR_USER_LOGIN_INFO _loginInfo = new CHCNetSDK.NET_DVR_USER_LOGIN_INFO
        {
            sDeviceAddress = new byte[CHCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN],
            sUserName = new byte[CHCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN],
            sPassword = new byte[CHCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN]
        };

        private CHCNetSDK.NET_DVR_JPEGPARA _jpegParam = new CHCNetSDK.NET_DVR_JPEGPARA
        {
            wPicSize = 5,
            wPicQuality = 1
        };

        private NET_DVR_PREVIEWINFO _previewINfo = new NET_DVR_PREVIEWINFO
        {
            lChannel = 1,
            dwStreamType = 1,
            dwLinkMode = 4,
            bBlocked = true,
        };

        private static NET_DVR_SETUPALARM_PARAM _struSetupParam = new NET_DVR_SETUPALARM_PARAM
        {
            byLevel = 1, //布防优先级：0- 一等级（高），1- 二等级（中）   
            byAlarmInfoType = 1, //上传报警信息类型: 0- 老报警信息(NET_DVR_PLATE_RESULT), 1- 新报警信息(NET_ITS_PLATE_RESULT)
        };

        public override Task<bool> ToggleGateSwitchCmdAsync(bool open)
        {
            using var db = DbServiceBridgeHandle();

            var cfgJson = db.SystemConfigDictionaries
                    .Where(p => p.Key == SystemConfigKey.EntryConfig)
                    .Select(p => p.StringValue).FirstOrDefault();

            var cfg = CommonUtil.TryGetJSONObject<EntryConfig>(cfgJson) ?? new EntryConfig();

            if (DeviceBusyOrError || cfg.DisableGateControl)
            {
                return Task.FromResult(false);
            }

            return Task.Run(() => RemoteControl(open ? BarrierCtrlType.开启 : BarrierCtrlType.关闭));
        }

        public override void Open()
        {
            _ctrl.Dispatcher.Invoke(() => SetBusyOrError("加载中..."));

            if (Login())
            {
                if (!OnlyMonitor)
                {
                    SetupAlarm();
                }
            }

            RTSPUrl = $"rtsp://{LoginName}:{LoginPassword}@{IP}:554/h264/ch1/sub/av_stream";
            if (string.IsNullOrWhiteSpace(RTSPUrl))
            {
                _ctrl.Dispatcher.Invoke(() => SetBusyOrError("未配置RTSP链接"));
            }
            else
            {
                StartVideo();
            }

        }

        private bool Login()
        {
            try
            {
                _loginInfo.wPort = Convert.ToUInt16(8000);
                Encoding.UTF8.GetBytes(IP).CopyTo(_loginInfo.sDeviceAddress, 0);
                Encoding.UTF8.GetBytes(LoginName).CopyTo(_loginInfo.sUserName, 0);
                Encoding.UTF8.GetBytes(LoginPassword).CopyTo(_loginInfo.sPassword, 0);

                _deviceHandle = CHCNetSDK.NET_DVR_Login_V40(ref _loginInfo, ref _deviceInfo);

                if (_deviceHandle == -1)
                {
                    var msg = CHCNetSDK.GetErrorMsg();
                    msg = msg == "没有错误" ? "登录失败" : msg;
                    _ctrl.Dispatcher.Invoke(() => SetBusyOrError(msg));

                    return false;
                }

                _ctrl.Dispatcher.Invoke(() =>
                {
                    DeviceBusyOrError = false;
                    Message = string.Empty;
                });

                return true;
            }
            catch (Exception e)
            {
                Logger.Error($"{Type} 登录失败:{IP}", e);
                _ctrl.Dispatcher.Invoke(() => SetBusyOrError($"登录失败：{e.Message}"));

            }
            return false;
        }

        private void SetupAlarm()
        {
            try
            {

                if (_deviceHandle == -1)
                {
                    return;

                }
                // 初始化车牌识别
                _struSetupParam.dwSize = (uint)Marshal.SizeOf(_struSetupParam);
                _alarmHandleId = NET_DVR_SetupAlarmChan_V41(_deviceHandle, ref _struSetupParam);

                if (_alarmHandleId == -1)
                {
                    _ctrl.Dispatcher.Invoke(() => SetBusyOrError($"布防失败：{CHCNetSDK.GetErrorMsg()}"));

                    return;
                }
                _ctrl.Dispatcher.Invoke(() =>
                {
                    DeviceBusyOrError = false;
                    Message = string.Empty;
                });

            }
            catch (Exception e)
            {
                Logger.Error($"{Type} LPR布防失败:{IP}", e);
                _ctrl.Dispatcher.Invoke(() => SetBusyOrError($"布防失败：{e.Message}"));
            }

        }

        public override void Close()
        {
            ExitVideo();
        }

        private bool RemoteControl(BarrierCtrlType type)
        {
            var @params = new NET_DVR_BARRIERGATE_CFG
            {
                dwChannel = 1,
                byLaneNo = 1,
                byBarrierGateCtrl = (byte)type,
                byEntranceNo = 1,
                byUnlock = 0
            };

            var nSize = Marshal.SizeOf(@params);
            @params.dwSize = (uint)nSize;

            var ptrPtzCfg = Marshal.AllocHGlobal(nSize);
            Marshal.StructureToPtr(@params, ptrPtzCfg, false);
            var result = NET_DVR_RemoteControl(_deviceHandle, NET_DVR_BARRIERGATE_CTRL, ptrPtzCfg, nSize);
            Logger?.Info(result ? $"{IP}-{Type}道闸已{type}:参数：{CommonUtil.AJSerializeObject(@params)}" : $"{IP}-{Type}道闸控制失败：{GetErrorMsg()}");
            return result;
        }

        protected override async void OnDeviceReceiveCmdEvent(DeviceReceiveCmdEventArgs e)
        {
            switch (e.Type)
            {
                case DeviceReceiveCmdType.开闸:
                    if (e.DeviceId != Id)
                    {
                        return;
                    }
                    await ToggleGateSwitchCmdAsync(true);
                    break;
                case DeviceReceiveCmdType.录像:
                    var captureParam = (DeviceVideoCaptureCmdParameter)e.Data;
                    if (PassagewayId != e.PassagewayId)
                    {
                        return;
                    }
                    await StartVideoCapture(captureParam);
                    break;
                default:
                    break;
            }


        }

        public async Task<ProcessResult> StartVideoCapture(DeviceVideoCaptureCmdParameter parameter)
        {
            Logger?.Debug($"{IP} {Type}收到录像事件参数:设备id:{Id};道闸id:{PassagewayId};时长:{parameter.VideoDuration};位置:{parameter.StoreDirectory}");

            var result = new ProcessResult();
            if (parameter.VideoDuration <= 0)
            {
                result.SetError("视频时长参数有误");
                return result;
            }
            var fileName = string.Empty;
            try
            {
                if (_realPlayHandle == -1)
                {
                    _realPlayHandle = NET_DVR_RealPlay_V40(_deviceHandle, ref _previewINfo, null, IntPtr.Zero);
                }

                if (_realPlayHandle == -1)
                {
                    result.SetError($"{IP} {Type} 实时播放设置失败:{GetErrorMsg()}");
                    Logger?.Error(result.Message);
                    return result;
                }

                if (!Directory.Exists(parameter.StoreDirectory))
                {
                    Directory.CreateDirectory(parameter.StoreDirectory);
                }

                var carNo = parameter.CarPlateNumber ?? "未知车牌";

                fileName = Path.Combine(parameter.StoreDirectory, $"{carNo}_{WatchhouseName}_{PassagewayName}_{IP.Replace(".", "-")}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.mp4");

                var videoResult = NET_DVR_SaveRealData_V30(_realPlayHandle, 0x2, fileName);

                if (!videoResult)
                {
                    result.SetError($"{IP} {Type} 录屏失败:{GetErrorMsg()}---fileName:{fileName}");
                    Logger?.Error(result.Message);
                    return result;
                }

                await Task.Delay(Convert.ToInt32(TimeSpan.FromSeconds(parameter.VideoDuration).TotalMilliseconds));

                NET_DVR_StopSaveRealData(_realPlayHandle);

                result.SetSuccess(fileName);
            }
            catch (Exception e)
            {
                result.SetError($"{IP} {Type} 录屏异常:{e.Message}---fileName:{fileName}");
                Logger?.Error(result.Message, e);
            }

            return result;
        }

    }
}
